using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;
using Microsoft.ApplicationBlocks.Updater;

namespace AutoInproc
{
	/// <summary>
	/// Summary description for ManualInprocForm.
	/// </summary>
	public class AutoInprocForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Button exitButton;
		private System.Windows.Forms.ListBox eventList;
		private Thread pollThread = null;
		
		private int manifestDownloaded = 0;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public AutoInprocForm()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if(pollThread != null)
			{
				pollThread.Abort();
			}
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.label1 = new System.Windows.Forms.Label();
			this.exitButton = new System.Windows.Forms.Button();
			this.eventList = new System.Windows.Forms.ListBox();
			this.SuspendLayout();
			// 
			// label1
			// 
			this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 10.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.label1.Location = new System.Drawing.Point(24, 32);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(224, 23);
			this.label1.TabIndex = 0;
			this.label1.Text = "This is the base version 1.0";
			// 
			// exitButton
			// 
			this.exitButton.Location = new System.Drawing.Point(40, 184);
			this.exitButton.Name = "exitButton";
			this.exitButton.TabIndex = 3;
			this.exitButton.Text = "Exit";
			this.exitButton.Click += new System.EventHandler(this.exitButton_Click);
			// 
			// eventList
			// 
			this.eventList.HorizontalScrollbar = true;
			this.eventList.Location = new System.Drawing.Point(24, 64);
			this.eventList.Name = "eventList";
			this.eventList.Size = new System.Drawing.Size(240, 95);
			this.eventList.TabIndex = 4;
			// 
			// AutoInprocForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(292, 266);
			this.Controls.Add(this.eventList);
			this.Controls.Add(this.exitButton);
			this.Controls.Add(this.label1);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
			this.MaximizeBox = false;
			this.Name = "AutoInprocForm";
			this.Text = "AutoInprocForm";
			this.Load += new System.EventHandler(this.AutoInprocForm_Load);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
            Control.CheckForIllegalCrossThreadCalls = false; 
            Application.Run(new AutoInprocForm());            
			
		}

		private void CheckAndUpdate()
		{
			try
			{
				// Get the updater manager
				ApplicationUpdaterManager updater = ApplicationUpdaterManager.GetUpdater();
				
				// Subscribe for various events
				updater.DownloadStarted +=new DownloadStartedEventHandler(updater_DownloadStarted);
				updater.DownloadProgress += new DownloadProgressEventHandler(updater_DownloadProgress);
				updater.DownloadCompleted += new DownloadCompletedEventHandler(updater_DownloadCompleted);
				updater.DownloadError += new DownloadErrorEventHandler(updater_DownloadError);
				updater.ActivationInitializing += new ActivationInitializingEventHandler(updater_ActivationInitializing);
				updater.ActivationStarted += new ActivationStartedEventHandler(updater_ActivationStarted);
				updater.ActivationInitializationAborted += new ActivationInitializationAbortedEventHandler(updater_ActivationInitializationAborted);
				updater.ActivationError += new ActivationErrorEventHandler(updater_ActivationError);
				updater.ActivationCompleted +=new ActivationCompletedEventHandler(updater_ActivationCompleted);

				// Loop till the updates are available

				Manifest[] manifests = null;
				while(true)
				{
					manifests = updater.CheckForUpdates();
					if(manifests.Length > 0)
					{
						// Prompt user if he wants to apply the updates
						if( MessageBox.Show(this,"Update for Auto Inproc Application is available, do you want to apply the update?","Update",MessageBoxButtons.YesNo)== DialogResult.Yes)
						{
							foreach(Manifest m in manifests)
							{
								m.Apply = true;
							}
							// update the application as per manifest details.
							updater.Download( manifests, TimeSpan.MaxValue );
							if(manifestDownloaded == manifests.Length)
							{
								updater.Activate( manifests );
								manifestDownloaded = 0;
							}
							break;
						}
						else
						{
							Thread.Sleep(10000);
						}
					}
					else
					{
						Thread.Sleep(10000);
					}
				}
			}
			catch(ThreadAbortException ex)
			{
				// Do nothing if the thread is being aborted, as we are explicitly doing it
			}
			catch(Exception ex)
			{
				MessageBox.Show(this,ex.Message,"Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
			}
		}

		private void exitButton_Click(object sender, System.EventArgs e)
		{
			Application.Exit();
		}

		private void updater_DownloadStarted(object sender, DownloadStartedEventArgs e)
		{
			UpdateList("DownloadStarted for manifest: " + e.Manifest.ManifestId);
		}

		private void updater_DownloadProgress(object sender, DownloadProgressEventArgs e)
		{
			UpdateList("DownloadProgress for manifest: "+ e.Manifest.ManifestId +
				"- Files: "+e.FilesTransferred+"/"+e.FilesTotal+
				" - Bytes: "+e.BytesTransferred+"/"+e.BytesTotal);
		}

		private void updater_DownloadCompleted(object sender, ManifestEventArgs e)
		{
			UpdateList("DownloadCompleted for manifest: " + e.Manifest.ManifestId);
			manifestDownloaded++;
		}

		private void updater_DownloadError(object sender, ManifestErrorEventArgs e)
		{
			UpdateList("DownloadError for manifest: " + e.Manifest.ManifestId +"\n"+e.Exception.Message);
		}

		private void updater_ActivationInitializing(object sender, ManifestEventArgs e)
		{
			UpdateList("ActivationInitializing for manifest: " + e.Manifest.ManifestId);
		}

		private void updater_ActivationStarted(object sender, ManifestEventArgs e)
		{
			UpdateList("ActivationStarted for manifest: " + e.Manifest.ManifestId);
		}

		private void updater_ActivationInitializationAborted(object sender, ManifestEventArgs e)
		{
			UpdateList("ActivationInitializationAborted for manifest: " + e.Manifest.ManifestId);
			MessageBox.Show(this,"The Application needs to restart for applying the updates, please restart the application.",
				"Auto Inproc Updates",MessageBoxButtons.OK,MessageBoxIcon.Information);
		}

		private void updater_ActivationError(object sender, ManifestErrorEventArgs e)
		{
			UpdateList("ActivationError for manifest: " + e.Manifest.ManifestId +"\n"+e.Exception.Message);
		}

		private void updater_ActivationCompleted(object sender, ActivationCompleteEventArgs e)
		{
			UpdateList("ActivationCompleted for manifest: " + e.Manifest.ManifestId);
		}

        private delegate void UpdateListDelegate(string displayString);

        private void UpdateList(string displayString)
        {
            if (InvokeRequired)
                BeginInvoke(new UpdateListDelegate(InnerUpdateList), displayString);
            else
                InnerUpdateList(displayString);

        }

        private void InnerUpdateList(string displayString)
        {
            eventList.Items.Add(displayString);
            eventList.Update();
        }

		private void AutoInprocForm_Load(object sender, System.EventArgs e)
		{
			// Seperate thread is spun to keep polling for updates
			ThreadStart checkUpdateThreadStart = new ThreadStart(CheckAndUpdate);
			pollThread = new Thread(checkUpdateThreadStart);
			pollThread.Start();		
		}

		
	}
}
